package com.wanger.swc.util.template;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;

import java.io.*;
import java.nio.file.Files;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * @Author: wanger
 * @Date: 2024/9/20 14:49
 * @Description:
 */
@Slf4j
public class MyFileUtil {
    public static final String tmpFilePath;

    static {
        tmpFilePath = getTmpFilePath();
    }

    /**
     * 获取临时文件路径，判断tmpFilePath末尾是否为fileSeparator，是则直接返回，
     * 不是则拼接上fileSeparator后返回。
     *
     * @return 临时文件路径
     */
    public static String getTmpFilePath() {
        String tmpPath = FileUtil.getTmpDirPath();//获取系统临时文件路径
        String fileSeparator = File.separator;//获取系统分隔符
        // 检查 tmpFilePath 末尾是否以 fileSeparator 结尾
        if (tmpPath.endsWith(fileSeparator)) {
            // 如果是，则直接返回
            return tmpPath;
        } else {
            // 如果不是，则拼接上 fileSeparator
            return tmpPath + fileSeparator;
        }
    }

    /**
     * 获取临时文件路径
     *
     * @param isUuid 是否使用UUID
     * @return 文件路径
     */
    public static String getTmpFileNamePath(boolean isUuid) {
        return getTmpFilePath() + getFileName(isUuid);
    }

    /**
     * 压缩文件到输出流
     *
     * @param file 要压缩的文件
     */
    public static byte[] zipFile(File file) {
        // 临时文件路径
        String filePath = tmpFilePath + IdUtil.fastSimpleUUID() + ".zip";
        try (FileOutputStream fos = new FileOutputStream(filePath)) {
            zipFile(file, fos);
            // 把zos输出流转换为byte[]数据
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            Files.copy(new File(filePath).toPath(), baos);
            return baos.toByteArray();
        } catch (IOException e) {
            log.error("文件压缩失败！", e);
        }
        return new byte[0];
    }

    /**
     * 压缩文件到输出流
     *
     * @param file 要压缩的文件
     * @param fos  输出流
     */
    public static void zipFile(File file, OutputStream fos) {
        try (ZipOutputStream zos = new ZipOutputStream(fos)) {
            zipFile(file, file.getName(), zos);
        } catch (IOException e) {
            log.error("文件压缩失败！", e);
        } finally {
            IoUtil.close(fos);
        }
    }

    /**
     * 压缩文件
     *
     * @param fileToZip 要压缩的文件
     * @param fileName  文件名称
     * @param zos       压缩输出流
     * @throws IOException IO异常
     */
    private static void zipFile(File fileToZip, String fileName, ZipOutputStream zos) throws IOException {
        if (fileToZip.isHidden()) {
            return;
        }
        if (fileToZip.isDirectory()) {
            if (fileName.endsWith("/")) {
                zos.putNextEntry(new ZipEntry(fileName));
            } else {
                zos.putNextEntry(new ZipEntry(fileName + "/"));
            }
            zos.closeEntry();
            File[] children = fileToZip.listFiles();
            if (children != null) {
                for (File childFile : children) {
                    zipFile(childFile, fileName + "/" + childFile.getName(), zos);
                }
            }
            return;
        }
        try (FileInputStream fis = new FileInputStream(fileToZip)) {
            ZipEntry zipEntry = new ZipEntry(fileName);
            zos.putNextEntry(zipEntry);
            byte[] bytes = new byte[1024];
            int length;
            while ((length = fis.read(bytes)) >= 0) {
                zos.write(bytes, 0, length);
            }
        }
    }


    /**
     * 获取文件名称
     *
     * @param isUuid 是否使用UUID
     * @return 文件名称
     */
    public static String getFileName(boolean isUuid) {
        if (isUuid) {
            return IdUtil.fastSimpleUUID();
        } else {
            return DateUtil.format(DateUtil.date(), DatePattern.PURE_DATETIME_MS_PATTERN);
        }
    }

    /**
     * 构建文件
     *
     * @param fileData 文件数据
     * @return 文件对象
     */
    public static File builderFile(FileData fileData) {
        return builderFileImpl(new FileData(getFileName(true)).addChild(fileData));
    }

    /**
     * 构建文件
     *
     * @param fileData 文件数据
     * @return 文件对象
     */
    private static File builderFileImpl(FileData fileData) {
        log.info("获取到的临时文件路径【{}】", tmpFilePath);
        File file = new File(tmpFilePath + fileData.getName());
        // 如果有子文件，创建文件夹
        if (CollUtil.isNotEmpty(fileData.getChildren())) {
            // 递归构建子文件和文件夹
            for (FileData child : fileData.getChildren()) {
                File childFile = builderFileImpl(child);// 递归调用
                //FileUtil.move()会自动创建文件夹
                FileUtil.move(childFile, new File(file, childFile.getName()), true);
            }
        } else {
            // 如果没有子文件，创建文件并写入内容
            if (StrUtil.isNotBlank(fileData.getFileContent())) {
                // 写入文件内容，FileUtil.writeUtf8String()会自动创建子文件
                FileUtil.writeUtf8String(fileData.getFileContent(), file);
            } else FileUtil.writeUtf8String("", file);
        }
        return file;
    }

}
